package com.pyl.admin.system.controller;

import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.pyl.admin.core.constant.AdminConst;
import com.pyl.admin.core.enums.MenuTypeEnum;
import com.pyl.admin.core.enums.ResultEnum;
import com.pyl.admin.core.enums.StatusEnum;
import com.pyl.admin.core.exception.ResultException;
import com.pyl.admin.core.shiro.ShiroUtil;
import com.pyl.admin.system.entity.SysFile;
import com.pyl.admin.system.entity.SysMenu;
import com.pyl.admin.system.entity.SysUser;
import com.pyl.admin.system.service.SysMenuService;
import com.pyl.admin.system.service.SysUserService;
import com.pyl.admin.system.validator.UserForm;
import com.pyl.core.enums.LingResultEnum;
import com.pyl.core.utils.ResultVoUtil;
import com.pyl.core.utils.SpringContextUtil;
import com.pyl.core.vo.ResultVo;
import com.pyl.core.wraps.URL;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author 灵魂贰婶
 * @since 2019-06-28
 */
@Controller
public class SysMainController {

	@Autowired
	private SysMenuService sysMenuService;

	@Autowired
	private SysUserService sysUserService;

	/**
	 * 后台主体内容
	 */
	@GetMapping("/")
	@RequiresPermissions("/main")
	public String main(Model model) {
		// 获取当前登录的用户
		SysUser user = ShiroUtil.getSubject();
		// 菜单键值对(ID->菜单)
		Map<Long, SysMenu> keyMenu = new HashMap<>();
		// 管理员实时更新菜单
		if (user.getId().equals(AdminConst.ADMIN_ID)) {
			List<SysMenu> sysMenus = sysMenuService.selectList(new EntityWrapper<SysMenu>()
					.eq("status", Integer.valueOf(StatusEnum.OK.getCode())).orderAsc(Arrays.asList("sort")));
			sysMenus.forEach(menu -> keyMenu.put(menu.getId(), menu));
		} else {
			// 其他用户需从相应的角色中获取菜单资源
			user.getRoles().forEach(role -> {
				role.getSysMenus().forEach(menu -> {
					keyMenu.put(menu.getId(), menu);
				});
			});
		}

		// 封装菜单树形数据
		Map<Long, SysMenu> treeMenu = new HashMap<>();
		keyMenu.forEach((id, menu) -> {
			if (!menu.getType().equals(Integer.valueOf(MenuTypeEnum.NOT_MENU.getCode()))) {
				if (keyMenu.get(menu.getPid()) != null) {
					keyMenu.get(menu.getPid()).getChildren().put(Long.valueOf(menu.getSort()), menu);
				} else {
					if (menu.getType().equals(Integer.valueOf(MenuTypeEnum.TOP_LEVEL.getCode()))) {
						treeMenu.put(Long.valueOf(menu.getSort()), menu);
					}
				}
			}
		});

		model.addAttribute("user", user);
		model.addAttribute("treeMenu", treeMenu);
		return "/main";
	}

	/**
	 * 首页
	 */
	@GetMapping("/index")
	@RequiresPermissions("/index")
	public String index(Model model) {
		return "/system/main/index";
	}

	/**
	 * 跳转到个人信息页面
	 */
	@GetMapping("/user_info")
	@RequiresPermissions("/index")
	public String toUserInfo(Model model) {
		SysUser sysUser = ShiroUtil.getSubject();
		model.addAttribute("user", sysUser);
		return "/system/main/user_info";
	}

	/**
	 * 修改用户头像
	 */
	@PostMapping("/user_picture")
	@RequiresPermissions("/index")
	@ResponseBody
	public ResultVo<?> userPicture(@RequestParam("picture") MultipartFile picture, HttpServletResponse response) {
		UploadController uploadController = SpringContextUtil.getBean(UploadController.class);
		ResultVo<?> imageResult = uploadController.uploadPicture(picture);
		if (imageResult.getCode().equals(LingResultEnum.SUCCESS.getCode())) {
			SysUser sysUser = ShiroUtil.getSubject();
			sysUser.setPicture(((SysFile) imageResult.getData()).getPath());
			sysUser.setUpdateDate(new Date());
			sysUserService.updateById(sysUser);
			ShiroUtil.resetCookieRememberMe();
			return ResultVoUtil.SAVE_SUCCESS;
		} else {
			return imageResult;
		}
	}

	/**
	 * 保存修改个人信息
	 */
	@PostMapping("/user_info")
	@RequiresPermissions("/index")
	@ResponseBody
	public ResultVo<?> userInfo(@Validated UserForm userForm) {
		// 不允许修改用户名
		SysUser user = ShiroUtil.getSubject();
		if (!user.getUsername().equals(userForm.getUsername())) {
			throw new ResultException(ResultEnum.STATUS_UPDATE_USERNAME);
		}

		BeanUtil.copyProperties(userForm, user, CopyOptions.create().setIgnoreNullValue(true));
		user.setUpdateDate(new Date());
		// 保存数据
		sysUserService.updateById(user);
		ShiroUtil.resetCookieRememberMe();
		return ResultVoUtil.success("保存成功", new URL("/user_info"));
	}

	/**
	 * 跳转到修改密码页面
	 */
	@GetMapping("/edit_pwd")
	@RequiresPermissions("/index")
	public String toEditPwd() {
		return "/system/main/edit_pwd";
	}

	/**
	 * 保存修改密码
	 */
	@PostMapping("/edit_pwd")
	@RequiresPermissions("/index")
	@ResponseBody
	public ResultVo<?> editPwd(@RequestParam("original") String original, @RequestParam("password") String password,
			@RequestParam("confirm") String confirm) {
		// 判断原来密码是否有误
		SysUser oldPwdUser = ShiroUtil.getSubject();
		String oldPwd = ShiroUtil.encrypt(original, oldPwdUser.getSalt());
		if (original.isEmpty() || "".equals(original.trim()) || !oldPwd.equals(oldPwdUser.getPassword())) {
			throw new ResultException(ResultEnum.USER_OLD_PWD_ERROR);
		}

		// 判断密码是否为空
		if (password.isEmpty() || "".equals(password.trim())) {
			throw new ResultException(ResultEnum.USER_PWD_NULL);
		}

		// 判断两次密码是否一致
		if (!password.equals(confirm)) {
			throw new ResultException(ResultEnum.USER_INEQUALITY);
		}

		// 修改密码，对密码进行加密
		SysUser sysUser = sysUserService.selectById(oldPwdUser.getId());
		String salt = ShiroUtil.getRandomSalt();
		String encrypt = ShiroUtil.encrypt(password, salt);
		sysUser.setPassword(encrypt);
		sysUser.setSalt(salt);
		// 保存数据
		sysUserService.updateById(sysUser);
		ShiroUtil.getSubject().setPassword(encrypt);
		ShiroUtil.getSubject().setSalt(salt);
		ShiroUtil.resetCookieRememberMe();
		return ResultVoUtil.success("修改成功");
	}

}
